package com.ruoyi.js.controller;

import com.alibaba.fastjson.JSON;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.config.Global;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.json.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.js.domain.*;
import com.ruoyi.js.service.*;
import com.ruoyi.js.utils.ScoreUtils;
import com.ruoyi.js.webscoket.WebSocketUsers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 分数 Controller
 * 
 * @author greejoy
 * @date 2021-07-01
 */
@Controller
@RequestMapping("/js/app")
public class JsAppController extends BaseController
{

    private String prefix = "js/app";

    @Autowired
    private IJsScoreService jsScoreService;

    @Autowired
    private IJsScoreQueueService jsScoreQueueService;

    @Autowired
    private IJsMatchService jsMatchService;

    @Autowired
    private IJsPlaceService jsPlaceService;

    @Autowired
    private IJsRegisterService jsRegisterService;

    @Autowired
    private IJsItemService jsItemService;

    @Autowired
    private IJsMatchValueService jsMatchValueService;

    @Autowired
    private IJsJudgeService jsJudgeService;

    @Value(value = "${js.app.wsUrl}")
    private String wsUrl;

    @Value(value = "${js.app.key}")
    private String appKey;


    @GetMapping("/getMatchInfo")
    @ResponseBody
    public AjaxResult getMatchInfo(String key)
    {
        if(!appKey.equalsIgnoreCase(key)){
            return AjaxResult.error("验证信息错误");
        }

        Map result = new HashMap();

        JsMatch curMatch = jsMatchService.getCurrentScoreMatch();

        result.put("name", curMatch.getName());
        result.put("main", curMatch.getMainUnit());
        result.put("time", curMatch.getTime());
        result.put("address", curMatch.getAddress());

        List<JsJudge> judgeList = jsJudgeService.selectJsJudgeList(new JsJudge(curMatch.getId()));
        result.put("judgeList", judgeList);

        return AjaxResult.success(result);
    }

    @GetMapping("/getScoreInfo")
    @ResponseBody
    public AjaxResult getScoreInfo(String key, Long judgeId)
    {
        if(!appKey.equalsIgnoreCase(key)){
            return AjaxResult.error("验证信息错误");
        }

        Map result = new HashMap();

        JsMatch match = jsMatchService.getCurrentScoreMatch();
        if(match == null){
            throw new BusinessException("没有比赛正在打分");
        }

        JsScoreQueue scoreQueue = jsScoreQueueService.selectJsScoreQueueByJudgeId(judgeId);
        if(scoreQueue == null){
            return AjaxResult.error("没有该裁判打分信息");
        }

        JsRegister register = jsRegisterService.selectJsRegisterById(scoreQueue.getRegisterId());
        result.put("registerId", register.getId());

        JsItem item = jsItemService.selectJsItemById(register.getItemId());

        result.put("itemInfo", item.getName());

        String playerInfo = String.format("第%s轮 第%s号 %s", register.getSession(), register.getOdr(), register.getPlayerName());
        result.put("playerInfo", playerInfo);

        List<JsMatchValue> matchValueList = jsMatchValueService.selectJsMatchValueList(new JsMatchValue(register.getMatchId()));

        result.put("matchValueList", matchValueList);

        return AjaxResult.success(result);
    }


    @PostMapping("/saveScore")
    @ResponseBody
    @RepeatSubmit
    public AjaxResult saveScore(String key, Long judgeId, String valueStr)
    {

        if(!appKey.equalsIgnoreCase(key)){
            return AjaxResult.error("验证信息错误");
        }

        JsMatch match = jsMatchService.getCurrentScoreMatch();
        if(match == null){
            return AjaxResult.error("没有比赛正在打分");
        }

        JsScoreQueue scoreQueue = jsScoreQueueService.selectJsScoreQueueByJudgeId(judgeId);
        if(scoreQueue == null){
            return AjaxResult.error("没有该裁判打分信息");
        }

        Long registerId = scoreQueue.getRegisterId();

        JsJudge judge = jsJudgeService.selectJsJudgeById(judgeId);

        // 删除原有成绩
        List<JsScore> dbScoreList = jsScoreService.selectJsScoreList(new JsScore(registerId, null, judge.getId()));
        String ids = dbScoreList.stream().map(m -> m.getId().toString()).collect(Collectors.joining(","));
        if(ids.length() > 0){
            jsScoreService.deleteJsScoreByIds(ids);
        }

        // 添加新成绩
        List<JsMatchValue> matchValueList = JSON.parseArray(valueStr, JsMatchValue.class);
        List<JsScore> scoreList = new ArrayList<>();
        for (JsMatchValue matchValue : matchValueList) {
            JsScore score = new JsScore(registerId, matchValue.getId(), judgeId);
            score.setValue(matchValue.getScore());
            if(score.getValue() == null){
                score.setValue(0d);
            }
            scoreList.add(score);
        }

        jsScoreService.insertJsScoreBatch(scoreList);

        // 更新此裁判为已打分
        scoreQueue.setIsScored(true);
        jsScoreQueueService.updateJsScoreQueue(scoreQueue);

        // ws发送刷新成绩通知
        JSONObject object = new JSONObject();
        object.set("type", "refreshScore");
        WebSocketUsers.sendMessageToUsersByText(object.toCompactString());

        // 是否已经完成所有裁判打分
        if(jsRegisterService.checkAllJudgeScored(registerId)){
            // ws发送完成打分通知
            object = new JSONObject();
            object.set("type", "finishScore");
            object.set("registerId", registerId);
            WebSocketUsers.sendMessageToUsersByText(object.toCompactString());

            // 发送投屏信息
//            object = new JSONObject();
//            object.set("type", "screenScore");
//            object.set("registerId", registerId);
//            JsRegister register = jsRegisterService.selectJsRegisterById(registerId);
//            object.set("placeId", register.getPlaceId());
//            WebSocketUsers.sendMessageToUsersByText(object.toCompactString());
        }

        // 发送投屏信息
        object = new JSONObject();
        object.set("type", "screenScore");
        object.set("registerId", registerId);
        JsRegister register = jsRegisterService.selectJsRegisterById(registerId);
        object.set("placeId", register.getPlaceId());
        WebSocketUsers.sendMessageToUsersByText(object.toCompactString());

        return AjaxResult.success();
    }


    @GetMapping("sendScore")
    public String sendScore(String key, ModelMap mmap)
    {
        if(!appKey.equalsIgnoreCase(key)){
            throw new BusinessException("验证信息错误");
        }

        JsMatch match = jsMatchService.getCurrentScoreMatch();
        if(match == null){
            throw new BusinessException("没有比赛正在打分");
        }

        mmap.put("match", match);

        mmap.put("wsUrl", wsUrl);

        List<JsPlace> placeList = jsPlaceService.selectJsPlaceList(null);
        mmap.put("placeList", placeList);

        return prefix + "/sendScore";
    }


    /**
     * 查询报名列表
     */
    @GetMapping("/getRegisterList")
    @ResponseBody
    public AjaxResult getRegisterList(String key, Long placeId)
    {
        if(!appKey.equalsIgnoreCase(key)){
            return AjaxResult.error("验证信息错误");
        }

        JsRegister q_r = new JsRegister();
        q_r.setPlaceId(placeId);

        List<JsRegister> registerList = jsRegisterService.selectJsRegisterListToMatch(q_r);

        for (JsRegister register : registerList) {
            int size = register.getPlayerName().split(",").length;
            String playerName = size > 1 ? register.getPlayerName().substring(0, register.getPlayerName().indexOf(",")) + "+" + (size - 1) : register.getPlayerName();
            register.setPlayerName(playerName);
        }

        Map<Integer, List<JsRegister>> listMap = registerList.stream().collect(Collectors.groupingBy(JsRegister::getSession));

        List<List<JsRegister>> result = new ArrayList<>();
        for (Map.Entry<Integer, List<JsRegister>> entry : listMap.entrySet()) {
            result.add(entry.getValue());
        }

        return AjaxResult.success(result);
    }

    /**
     * 查询报名成绩
     */
    @GetMapping("/getRegisterScore")
    @ResponseBody
    public AjaxResult getRegisterScore(String key, Long registerId)
    {
        if(!appKey.equalsIgnoreCase(key)){
            return AjaxResult.error("验证信息错误");
        }
        JsRegister register = jsRegisterService.selectJsRegisterById(registerId);
        List<JsScore> scoreList = jsScoreService.selectJsScoreList(new JsScore(registerId, null, null));
        Map<Long, List<JsScore>> scoreListMap = scoreList.stream().collect(Collectors.groupingBy(JsScore::getJudgeId));
        JsPlace place = jsPlaceService.selectJsPlaceById(register.getPlaceId());
        List<JsJudge> judgeList = jsJudgeService.selectJsJudgeListByIds(place.getJudgeIds());
        for (JsJudge judge : judgeList) {
            List<JsScore> list = scoreListMap.get(judge.getId());
            if(list != null){
                Double score = list.stream().map(JsScore::getValue).reduce((sum, value) -> sum += value).orElse(null);
                judge.setScore(score);
                judge.setScoreList(list);
            }
        }
        return AjaxResult.success(judgeList);
    }

    @GetMapping("/sendToScore")
    @ResponseBody
    public AjaxResult sendToScore(String key, Long registerId)
    {
        if(!appKey.equalsIgnoreCase(key)){
            return AjaxResult.error("验证信息错误");
        }

        JsRegister register = jsRegisterService.selectJsRegisterById(registerId);
        JsPlace place = jsPlaceService.selectJsPlaceById(register.getPlaceId());
        List<JsJudge> judgeList = jsJudgeService.selectJsJudgeListByIds(place.getJudgeIds());

        // 删除报名已有队列
        jsScoreQueueService.deleteJsScoreQueueByRegisterId(registerId);
        for (JsJudge judge : judgeList) {
            jsScoreQueueService.deleteJsScoreQueueByJudgeId(judge.getId());
        }

        // 添加新队列
        for (JsJudge judge : judgeList) {
            jsScoreQueueService.insertJsScoreQueue(new JsScoreQueue(registerId, judge.getId()));
        }

        // 发送打分信息
        List<Long> judgeIds = judgeList.stream().map(JsJudge::getId).collect(Collectors.toList());
        JSONObject object = new JSONObject();
        object.set("type", "judgeScore");
        object.set("judgeIds", judgeIds);
        WebSocketUsers.sendMessageToUsersByText(object.toCompactString());

        // 发送投屏信息
        object = new JSONObject();
        object.set("type", "screenScore");
        object.set("registerId", registerId);
        object.set("placeId", register.getPlaceId());
        WebSocketUsers.sendMessageToUsersByText(object.toCompactString());

        return AjaxResult.success();
    }

    @GetMapping("/sendToScreenScore")
    @ResponseBody
    public AjaxResult sendToScreenScore(String key, Long registerId)
    {
        if(!appKey.equalsIgnoreCase(key)){
            return AjaxResult.error("验证信息错误");
        }

        JSONObject object = new JSONObject();
        object.set("type", "screenScore");
        object.set("registerId", registerId);
        JsRegister register = jsRegisterService.selectJsRegisterById(registerId);
        object.set("placeId", register.getPlaceId());

        // 发送投屏信息
        WebSocketUsers.sendMessageToUsersByText(object.toCompactString());

        return AjaxResult.success();
    }

    @GetMapping("/sendToScreenScore2")
    @ResponseBody
    public AjaxResult sendToScreenScore2(String key, Long registerId)
    {
        if(!appKey.equalsIgnoreCase(key)){
            return AjaxResult.error("验证信息错误");
        }

        JSONObject object = new JSONObject();
        object.set("type", "screenScore2");
        object.set("registerId", registerId);
        JsRegister register = jsRegisterService.selectJsRegisterById(registerId);
        object.set("placeId", register.getPlaceId());

        // 发送投屏信息
        WebSocketUsers.sendMessageToUsersByText(object.toCompactString());

        return AjaxResult.success();
    }


}
